package com.zjcode.cdcer.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.baomidou.mybatisplus.extension.api.R;
import com.chinatechstar.component.commons.entity.MPage;
import com.chinatechstar.component.commons.result.PaginationBuilder;
import com.chinatechstar.component.commons.service.AliyunOssService;
import com.chinatechstar.component.commons.service.BaseService;
import com.chinatechstar.component.commons.supports.PageData;
import com.chinatechstar.component.commons.utils.ExcelUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zjcode.cdcer.config.MConsts.Common;
import com.zjcode.cdcer.mapper.CerSysteminitImportOfficialInfoMapper;
import com.zjcode.cdcer.mapper.SequenceMapper;
import com.zjcode.cdcer.model.*;
import com.zjcode.cdcer.model.basic.JsonObj;
import com.zjcode.cdcer.model.excel.SysteminitImportInfo;
import com.zjcode.cdcer.pojo.CerSysteminitImportInfo;
import com.zjcode.cdcer.service.*;
import com.zjcode.cdcer.utils.Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CerSysteminitImportOfficialInfoServiceImpl implements
                                                        CerSysteminitImportOfficialInfoService,
                                                        BaseService {

    @Autowired
    private CerSysteminitImportOfficialInfoMapper cerSysteminitImportOfficialInfoMapper;
    @Autowired
    private CerSysteminitImportInfoService cerSysteminitImportInfoService;
    @Autowired
    private CerDetaildataImportInfoService cerDetaildataImportInfoService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysDictService sysDictService;
    @Autowired
    private SequenceMapper sequenceMapper;
    @Autowired
    private CerPersonInfoService cerPersonInfoService;
    @Autowired
    private TkmSysOrgService tkmSysOrgService;
    @Value("${studio.cer-personinfo-file-in-disk}")
    private String cerPersonFileInDisk;
    @Autowired
    private TkmEndoscopeDiagnoseNounInfoService endoscopeDiagnoseNounInfoService;
    @Autowired
    private AliyunOssService aliyunOssService;
    @Override
    public JsonObj insertOfficeInfo(PageData pageData) {
        Map<String, Object> data = new HashMap<>();
        data.put("count", 0);
        // 获取初始数据上报中的数据
        List<CerSysteminitImportInfo> list = cerSysteminitImportInfoService.getAllNoErrorData(
            pageData);
        if (!CollectionUtils.isEmpty(list)) {

//            List<CerSysteminitImportInfo> officialtList = new ArrayList<>();

            // 遍历出ext_flag_2不是0|0|0的数据
            List<CerSysteminitImportInfo> tmpList1 = list
                .stream()
                .filter(each -> {
                    String extFlag2 = each.getExtFlag2();
                    return !StringUtils.equals(extFlag2, "0|0|0");
                })
                .collect(Collectors.toList());

//            officialtList.addAll(tmpList1);

           /* // 遍历list,通过组装出最高诊断代码,判断出需要插入到officialtList中的数据
            List<CerSysteminitImportInfo> tmpList2 = list
                .stream()
                .filter(each -> {
                    String maxCode = each.getMaxCode();
                    String[] split = maxCode.split("\\|");
                    boolean bo = false;
                    // 此处之所以为3,表示12指肠的诊断代码不再判断之内
                    for (int i = 0; i < 3; i++) {
                        String s = split[i];
                        long count = Common.DIAGNOSTIC_CODE_LIST
                            .stream()
                            .filter(str -> {
                                boolean equals = str.equals(s);
                                if (equals) {
                                    log.info("诊断代码:{}-{}", s, str);
                                }
                                return equals;
                            })
                            .count();
                        if (count > 0) {
                            bo = true;
                            break;
                        }
                    }

                    return bo;
                })
                .collect(Collectors.toList());

            if (!CollectionUtils.isEmpty(tmpList2)) {
                // 去重
                tmpList2.removeIf(each -> {
                    long count = officialtList
                        .stream()
                        .filter(each2 -> {
                            return each2
                                .getId()
                                .equals(each.getId());
                        })
                        .count();
                    return count > 0;
                });
                officialtList.addAll(tmpList2);
            }

            // 移除list中将要被上传到详情数据表的数据
            list.removeAll(officialtList);

            // 针对详情库中的数据进行错误验证
            officialtList
                .parallelStream()
                .forEach(each -> {
                    String extFlag2 = each.getExtFlag2();
                    if (StringUtils.isEmpty(extFlag2)) {
                        // 构造出extflag2
                        // 获取食管病理诊断代码
                        extFlag2 = getExtFlag2(each);
                        each.setExtFlag2(extFlag2);
                    }

                });*/

            // 插入初始数据正式库
            if (CollectionUtils.isNotEmpty(list)) {
                cerSysteminitImportOfficialInfoMapper.insertOfficeInfo(list);
            }

            // 插入详情数据上报库
/*            if (CollectionUtils.isNotEmpty(officialtList)) {

                cerDetaildataImportInfoService.batchInsert(officialtList);
            }*/

            int count = list.size();
//                    + officialtList.size();
            data.put("count", count);

            // 修改原初始数据上报库中的数据状态
            cerSysteminitImportInfoService.updateCerSysteminitImportInfoStatus(pageData);
            return JsonObj.success(data);
        }
        return JsonObj.success(data);
    }

    @Override
    public Map<String, Object> listAllTableData(PageData pageData) {
        String userId = (String) pageData.get("user");
        if (StringUtils.isNotEmpty(userId)) {
            String extFlag = sysUserService.findUserExtFlag(userId);
            pageData.put("extFlag", extFlag);
        }
        // 读取区域信息
        pageData = Utils.transitionRegionInfo(pageData);
        MPage mPage = getPageInfo(pageData);
        List<SysDict> allCerDicts = sysDictService.findAllCerDicts();
        Map<String, List<SysDict>> keyListMap = allCerDicts
            .stream()
            .collect(Collectors.groupingBy(SysDict::getDictType));
        Page<Object> page = PageHelper.startPage(mPage.getCurrentPage(), mPage.getPageSize());
        List<LinkedHashMap<String, Object>> mapList = cerSysteminitImportOfficialInfoMapper.listAllTableData(
            pageData);
        keyListMap
            .entrySet()
            .parallelStream()
            .forEach(entry -> {
                // key
                String key = entry.getKey();
                if (key.equals("xb_code")) {
                    key = "sex";
                }
                List<SysDict> dicts = entry.getValue();
                String finalKey = key;
                mapList
                    .stream()
                    .forEach(map -> {
                        String obj = String.valueOf(map.get(finalKey));
                        if (obj != null) {
                            Optional<SysDict> first = dicts
                                .stream()
                                .filter(sysDict -> sysDict
                                    .getDictValue()
                                    .equals(obj))
                                .findFirst();
                            first.ifPresent(sysDict -> {
                                map.put(finalKey, sysDict.getDictName());
                            });
                        }
                    });
            });

        // 还原内镜诊断
        mapList
            .parallelStream()
            .forEach(map -> {
                String njzd = (String) map.get("njzd");
                List<String> ids = Arrays.asList(njzd.split(","));
                List<TkmEndoscopeDiagnoseNounInfo> nounInfos = endoscopeDiagnoseNounInfoService.selectByNounIds(
                    ids);
                if (nounInfos != null) {
                    map.put("njzd",
                            nounInfos
                                .stream()
                                .map(TkmEndoscopeDiagnoseNounInfo::getName)
                                .collect(Collectors.joining(",")));
                } else {
                    map.put("njzd", "");
                }
            });

        // 身份证, 给身份证加上掩码
        mapList
            .parallelStream()
            .forEach(each -> {
                String sfz = (String) each.get("sfz");
                if (sfz != null) {
                    each.put("sfz", sfz.substring(0, 6) + "********" + sfz.substring(14));
                }
            });

        return PaginationBuilder.buildResult(mapList,
                                             page.getTotal(),
                                             mPage.getCurrentPage(),
                                             mPage.getPageSize());
    }

    @Override
    public CerSysteminitImportOfficialInfo findDataById(String id) {
        return cerSysteminitImportOfficialInfoMapper.findDataById(id);
    }

    @Override
    public int deleteDataById(String id) {
        return cerSysteminitImportOfficialInfoMapper.deleteDataById(id);
    }

    @Override
    public List<LinkedHashMap<String, Object>> queryAllExportDataBy(PageData pageData) {

        String userId = (String) pageData.get("user");
        Object ids = pageData.get("ids");

        String extFlag = sysUserService.findUserExtFlag(userId);
        pageData.put("extFlag", extFlag);

        // 获取ids
        List<String> idList = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(ids)) {
            idList.addAll(Arrays.asList(String.valueOf(ids).split("\\|")));
            pageData.put("idList", idList);
        }

        List<LinkedHashMap<String, Object>> infoList = cerSysteminitImportOfficialInfoMapper.queryAllExportData(
            pageData,ids);

        if (CollectionUtils.isEmpty(infoList)) {
            return infoList;
        }
        List<SysDict> allCerDicts = sysDictService.findAllCerDicts();
        Map<String, List<SysDict>> keyListMap = allCerDicts
                .stream()
                .collect(Collectors.groupingBy(SysDict::getDictType));
        keyListMap
                .entrySet()
                .parallelStream()
                .forEach(entry -> {
                    // key
                    String key = entry.getKey();
                    if (key.equals("xb_code")) {
                        key = "sex";
                    }
                    List<SysDict> dicts = entry.getValue();
                    String finalKey = key;
                    infoList
                            .stream()
                            .forEach(map -> {
                                Object o = map.get(finalKey);
                                if (o != null) {
                                    Optional<SysDict> first = dicts
                                            .stream()
                                            .filter(sysDict -> sysDict
                                                    .getDictValue()
                                                    .equals(o.toString()))
                                            .findFirst();
                                    first.ifPresent(sysDict -> {
                                        map.put(finalKey,
                                                Optional
                                                        .ofNullable(sysDict.getDictName())
                                                        .orElse(""));
                                    });
                                }
                            });
                });
        return infoList;
    }

    /**
     * 获取所有合格初始数据正式库的数据集合
     */
    @Override
    public JsonObj getNoErrorOfficeData() {
        //List<CerSysteminitImportOfficialInfo> data = cerSysteminitImportOfficialInfoMapper.getNoErrorOfficeData();
        //if (!org.springframework.util.CollectionUtils.isEmpty(data)) {
        //    List<CerSysteminitImportOfficialInfo> collect = data
        //        .stream()
        //        .parallel()
        //        .map(obj -> {
        //            obj.setId(get32UUID());
        //            return obj;
        //        })
        //        .collect(Collectors.toList());
        //    //插入详情数据上报数据表
        //    int result = cerDetaildataImportInfoService.batchInsert(collect);
        //    if (result > 0) {
        //        //插入成功
        //        return JsonObj.success("已保存！");
        //    }
        //}
        return JsonObj.success("保存失败！");
    }

    /**
     * 初始正式库：导入Excel先判断
     * 1、没有screening_id有没有,判断人员信息表存不存在该值
     *  => 1.1、没有，新增人员信息、初始数据表（逻辑删除）、初始正式库
     *     1.2、 有，先判断正式库存不存在该值，（1）存在，报错，提示“正式库已存在”
     *     （2）不存在，查初始表是否存在，存在，将初始表数据放入到正式库，临时表逻辑删除
     *
     * @param file
     * @param response
     * @param userId
     * @return
     */
    @Override
    public JsonObj importGJData(MultipartFile file, HttpServletResponse response, String userId) {
        ImportParams params = new ImportParams();
        params.setTitleRows(0);
        File tmpfile =cerSysteminitImportInfoService.commonImportConfig(file,userId);
        // 解析excel
        List<SysteminitImportInfo> list = ExcelImportUtil.importExcel(tmpfile, SysteminitImportInfo.class, params);
        // 数据过滤,国家来源的数据默认都是正确的，仅过滤名称为null的
        list = list.stream().filter(each -> com.chinatechstar.component.commons.utils.StringUtils.isNotEmpty(each.getName()) && !Objects.equals("测试",each.getName())).collect(Collectors.toList());
        int count = 0;
        // 执行数据写入
        List<LinkedHashMap<String, Object>> failList =new ArrayList<>();
        if (list.size() > 0) {
            List<LinkedHashMap<String, Object>> orgList = tkmSysOrgService.listAll(new PageData());
            List<TkmSysOrg> allOrgs = tkmSysOrgService.getAllOrgs();
            List<Object> orgNameList = orgList.stream().map(obj -> obj.get("org_name")).collect(Collectors.toList());
            // 导入的表中screeningId集合
            List<String> screeningIdsByImport = list.stream().map(SysteminitImportInfo::getScreeningId).collect(Collectors.toList());
            // screeningId集合：查出的库里、导入表中，都存在screeningId集合
            List<String> selectScreeningIds =cerSysteminitImportOfficialInfoMapper.getInitOfficalByScreeningIdsByImport(screeningIdsByImport);
            // 设置：导入的表中存在，而库中不存在list数据，设置errorFlag为1，其他数据，errorFlag设置成2
            list.forEach(item->{
                item.setErrorFlag(1);
                selectScreeningIds.forEach(e->{
                    if (Objects.equals(e,item.getScreeningId())) {
                        failList.add(cerSysteminitImportInfoService.getLinkedMapByList(item,"该对象,数据正式库中已经存在"));
                        item.setErrorFlag(2);
                    }
                });
                if (!orgNameList.contains(item.getInstitutionName())) {
                    failList.add(cerSysteminitImportInfoService.getLinkedMapByList(item,"机构名称,系统中不存在"));
                    item.setErrorFlag(2);
                }
            });
            // 成功的数据（过滤 errorFlag == 1【表格数据支持插入】成功），批量新增
            list = list.stream().filter(each -> each.getErrorFlag()==1).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(list)) {
                // 获取extFlag
                String extFlag = sysUserService.findUserExtFlag(userId);
                // 因数据量较大，用户只需要安徽省【34】数据 ,从redis中查
                List<CityEntity> allCityInfo = new ArrayList<>();
                List<CityEntity> allAreaInfo = new ArrayList<>();
                List<CityEntity> allStreetInfo = new ArrayList<>();
                List<CityEntity> allVillageInfo = new ArrayList<>();
                cerSysteminitImportInfoService.getRedisByAddressCode(allCityInfo,allAreaInfo,allStreetInfo,allVillageInfo);
                // 查库：根据导入的screeningIds 查 初始临时表中screening_id不为null的list
                List<CerSysteminitImportInfo> infosByImport=cerSysteminitImportInfoService.getAllInitImportsByScreeningIds(screeningIdsByImport);
                if (CollectionUtils.isNotEmpty(infosByImport)) {
                    list.forEach(item->{
                        infosByImport.forEach(each->{
                            each.setExist(1);
                            if (Objects.equals(item.getScreeningId(),each.getScreeningId())) {
                                item.setErrorFlag(3);
                                each.setExist(2);
                            }
                        });
                    });
                }
                //exist=2 : 说明临时表存在
                List<CerSysteminitImportInfo>  infoList = infosByImport.stream().filter(each -> each.getExist() == 2 ).collect(Collectors.toList());
                List<CerPersonalInfo> cerPersonalInfos = cerPersonInfoService.queryAllByLimit(new CerPersonalInfo());
                // 将临时表数据，直接插入正式库
                if (CollectionUtils.isNotEmpty(infoList)) {
                    List<CerSysteminitImportInfo>  insertOfficalList=new ArrayList<>();
                    infoList.forEach(item->{
                        cerPersonalInfos.forEach(each->{
                            if (Objects.equals(each.getScreeningId(),item.getScreeningId())) {
                                item.setCerPersonalInfo(each);
                                item.setDeleted(0);
                                item.setCreateBy(userId);
                                item.setIsHaveError(0);
                                item.setIsUploaded(0);
                                item.setIsUplpadTimeout(0);
                                item.setCountrySource("1");
                                insertOfficalList.add(item);
                            }
                        });
                    });
                    // 新增正式表
                    count += cerSysteminitImportOfficialInfoMapper.addBatchInitOfficalByInitList(insertOfficalList);
                    // 改变临时表状态
                    List<String> initIds = infoList.stream().map(CerSysteminitImportInfo::getId).collect(Collectors.toList());
                    cerSysteminitImportInfoService.updateBatchStatusByIds(initIds, 1);
                }
                //errorFlag=1 : 说明临时表不存在
                list = list.stream().filter(each -> each.getErrorFlag()==1).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(list)) {
                    list.forEach(item->{
                        // 编辑cer_personal_info表数据
                        cerSysteminitImportInfoService.setCerPersonalInfoCommon(item,userId,extFlag,allCityInfo,allAreaInfo,allStreetInfo,allVillageInfo,allOrgs);
                        // 编辑cer_systeminit_import_info表
                        cerSysteminitImportInfoService.setTkmSysteminitImportInfoCommon(item,userId,extFlag);
                    });
                    List<CerPersonalInfo> personalInfos = list.stream().map(SysteminitImportInfo::getCerPersonalInfo).collect(Collectors.toList());
                    // 对需要导入的数据进行验证
                    personalInfos
                            .forEach(each -> {
                                List<String> errors = Utils.validateCerPersonalInfoData(each);
                                each.setCountrySource("1");
                                if (errors.size() > 0) {
                                    each.setIsHaveError(1);
                                    each.setErrorMessage(String.join("|", errors));
                                } else {
                                    each.setIsHaveError(0);
                                    each.setErrorMessage("");
                                }
                            });
                    // 先新增cer_personal_info表
                    cerPersonInfoService.addBatchPersonals(personalInfos);
                    List<TkmSysteminitImportInfo> tkmSysteminitImportInfos = list.stream().map(SysteminitImportInfo::getTkmSysteminitImportInfo).collect(Collectors.toList());
                    tkmSysteminitImportInfos
                            .forEach(each->{
                                //对初始数据进行校验
                                List<String> errors = Utils.validateSysteminitImportInfoData(each);
                                String njzd = each.getNjzd();
                                if (ObjectUtils.isNotEmpty(njzd)) {
                                    List<String> names = Arrays.asList(njzd.split(","));
                                    List<TkmEndoscopeDiagnoseNounInfo> infos = endoscopeDiagnoseNounInfoService.selectByNounNames(names);
                                    if (CollectionUtils.isNotEmpty(infos)) {
                                        String idsStr = infos.stream().map(TkmEndoscopeDiagnoseNounInfo::getId).collect(Collectors.joining(","));
                                        each.setNjzd(idsStr);
                                    }
                                }
                                each.setDeleted(1);
                                each.setIsUploaded(1);
                                each.setCountrySource("1");
                                if (errors.size() > 0) {
                                    each.setIsHaveError(1);
                                    each.setErrorMessage(String.join("|", errors));
                                } else {
                                    each.setIsHaveError(0);
                                    each.setErrorMessage("");
                                }
                                personalInfos.forEach(item->{
                                    if (Objects.equals(item.getScreeningId(),each.getScreeningId())) {
                                        each.setCerPersonalInfo(item);
                                    }
                                });
                            });
                    // 再新增cer_systeminit_import_info表
                    cerSysteminitImportInfoService.addBatchInitImport(tkmSysteminitImportInfos);
                    // 最后新增正式表
                    count += cerSysteminitImportOfficialInfoMapper.addBatchInitOffical(tkmSysteminitImportInfos);
                }
            }
        }
        // 组装表头
        List<String> headList = Arrays.asList(
                "省份",
                "城市",
                "区县",
                "乡镇",
                "村",
                "机构名称",
                "调查对象ID号",
                "姓名",
                "性别",
//                "筛查类型",
                "生日",
                "民族",
                "身份证号",
                "地址",
                "联系电话",
                "筛查类型",
                "随访次数",
                "内镜号",
                "是否无痛",
                "染色类别",
                "是否活检",
                "内镜诊疗日期",
                "Hp",
                "Hp检测方法",
                "图片数量",
                "内镜诊断",
                "内镜诊断医师",
                "内镜审核医师",
                "病理号",
                "病理报告日期",
                "食管病理诊断代码",
                "贲门病理诊断代码",
                "胃病理诊断代码",
                "十二指肠病理诊断代码",
                "病理诊断医师",
                "病理审核医师",
                "病理诊断",
                "导入错误原因");
        try {
            // 导出
            if (CollectionUtils.isNotEmpty(failList)) {
//                String s = ExcelUtils.downloadExcel(headList, failList, "导入失败数据导出", response, cerPersonFileInDisk);
                File downloadExcelFile = ExcelUtils.downloadExcelFile(headList, failList, "导入失败数据导出", response, cerPersonFileInDisk);
                String upload = aliyunOssService.upload(downloadExcelFile);
                HashMap<String,Object> res =new HashMap<>();
                res.put("errorFile", upload);
                String msg ="导入失败"+failList.size()+"条";
                if (count>0) {
                    msg += "，导入成功"+count+"条数据";
                }
                return JsonObj.success(res,msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonObj.error("错误数据导出失败");
        }
        return JsonObj.success("导入成功"+count+"条数据");
    }


    private int getFlagByCode(String code) {
        if (StringUtils.isEmpty(code)) {
            return 0;
        }
        long count = Common.DIAGNOSTIC_CODE_LIST
            .stream()
            .filter(c -> {
                return c.equals(code);
            })
            .count();
        if (count > 0) {
            return 1;
        }
        return 0;
    }

    private String getExtFlag2(CerSysteminitImportInfo each) {
        String extFlag2;
        List<Integer> flags = new ArrayList<>();
        String sgblCode = each.getSgblCode();
        flags.add(getFlagByCode(sgblCode));
        // 获取贲门病理诊断代码
        String bmblCode = each.getBmblCode();
        flags.add(getFlagByCode(bmblCode));
        // 获取胃病理诊断代码
        String wblCode = each.getWblCode();
        flags.add(getFlagByCode(wblCode));
        extFlag2 = flags
            .stream()
            .map(String::valueOf)
            .collect(Collectors.joining(Common.DELIMITER_CHARACTER));
        return extFlag2;
    }
}
